/*
 * BaseDao.cpp
 *
 *  Created on: 2018年3月30日
 *      Author: yaoqiaobing
 */

#include "dao/BaseDao.hpp"
#include "lib_acl.h"
#include "stdlib/log.hpp"
#include "db/query.hpp"
#include "lib_acl.hpp"

#define STR acl_vstring_str

BaseDao::BaseDao(const acl::mysql_conf& mysqlConf, const char* xmlPath) {
	this->xmlPath_ = xmlPath;
	this->xmlData_ = NULL;
	this->xml_ = NULL;
	this->dbPoolFlag_ = false;

	this->dbHandleMysql_= new acl::db_mysql(mysqlConf);
}

BaseDao::BaseDao(acl::db_mysql* dbHandleMysql, const char* xmlPath) {
	this->xmlPath_ = xmlPath;
	this->xmlData_ = NULL;
	this->xml_ = NULL;
	this->dbPoolFlag_ = true;

	this->dbHandleMysql_= dbHandleMysql;
}

BaseDao::~BaseDao() {
	if (xml_ != NULL) {
		acl_xml_free(xml_);
	}

	if (xmlData_ != NULL) {
		acl_myfree(xmlData_);
	}

	if (dbHandleMysql_ != NULL && dbPoolFlag_ == false) {
		delete dbHandleMysql_;
	}

	std::map<std::string, std::pair<sql_type, acl::query*>>::iterator it = xmlSql_.begin();
	for (; it != xmlSql_.end(); it++) {
		delete (it->second).second;
	}
}

int BaseDao::createMysqlConnect() {
	if (dbHandleMysql_->is_opened()) {
		return 0;
	}

	// 先打开数据库连接
	if (dbHandleMysql_->open() == false)
	{
		return -1;
	}

	return 0;
}

int BaseDao::parseXml() {
	char *ptr;
	struct timeval begin, end;

	// 1.读出xml文件
	xmlData_ = acl_vstream_loadfile(xmlPath_.c_str());
	if (xmlData_ == NULL) {
		logger_error("fail to load xml: %s", xmlPath_.c_str());
		return -1;
	}

	gettimeofday(&begin, NULL);

	// 2.创建 xml 对象
	xml_ = acl_xml_alloc();

	// 3.一次性地分析完整 xml 数据
	ptr = xmlData_;
	acl_xml_parse(xml_, ptr);

	gettimeofday(&end, NULL);

	logger("success parse xml: %s, time: %ld seconds", xmlPath_.c_str(), end.tv_sec - begin.tv_sec);

	// 4.
    if (acl_xml_is_complete(xml_, "mapper")) {
    	logger("Yes, the xml complete");
    } else {
    	logger_warn("No, the xml not complete");
    }

    // 5.根据标签名获得 xml 结点集合
	sql_type_map sqlTypeMap;
	sql_type_map::iterator it = sqlTypeMap.begin();
	for (; it != sqlTypeMap.end(); it++) {
		// 查询出的节点集合
	    ACL_ARRAY* xmlNodeArr_ = acl_xml_getElementsByTagName(xml_, (it->second).c_str());
		if (xmlNodeArr_) {
			logger("xml get [%d] elements by tag: %s", xmlNodeArr_->count, (it->second).c_str());
			/* 遍历结果集 */
			ACL_ITER iter;
			acl_foreach(iter, xmlNodeArr_) {
				ACL_XML_NODE* node = (ACL_XML_NODE*) iter.data;
				ACL_XML_ATTR* attr = acl_xml_getElementAttr(node, "id");

				logger("tag: %s, id: %s, text: %s", STR(node->ltag), STR(attr->value), STR(node->text));

				acl::query* xmlSql = new acl::query();
				xmlSql->create_sql(STR(node->text));
				xmlSql_.insert(std::make_pair(STR(attr->value), std::make_pair(it->first, xmlSql)));
			}
	        /* 释放数组对象 */
	        acl_xml_free_array(xmlNodeArr_);
		} else {
			logger("xml get null elements by tag: %s", (it->second).c_str());
		}
	}

	return 0;
}

int BaseDao::daoInit() {
	// 打开连接
	if (createMysqlConnect() != 0) {
		return -1;
	}

	// 解析整个xml
	if (parseXml() != 0) {
		return -1;
	}

	return 0;
}

const acl::db_rows* BaseDao::execSql(std::string idStr, acl::query& query, int& affected_rows) {
	// 找到本函数对应的query
	logger("xml sql id is: %s", idStr.c_str());

	if (xmlSql_.find(idStr) == xmlSql_.end()) {
		logger_error("xml sql id: %s is not exist", idStr.c_str());
		return NULL;
	}
	sql_type sqlType = xmlSql_[idStr].first;
	acl::query* xmlQuery = xmlSql_[idStr].second;

	// 将用户设置的参数给入执行query中
	xmlQuery->set_params(query.get_params());

	const acl::db_rows* result = NULL;
	switch(sqlType) {
	case SQL_TYPE_INSERT:
		affected_rows = tbl_insert(*xmlQuery);
		logger("exec insert sql affect count is: %d", dbHandleMysql_->affect_count());
		break;
	case SQL_TYPE_DELETE:
		affected_rows = tbl_delete(*xmlQuery);
		logger("exec delete sql affect count is: %d", dbHandleMysql_->affect_count());
		break;
	case SQL_TYPE_UPDATE:
		affected_rows = tbl_update(*xmlQuery);
		logger("exec update sql affect count is: %d", dbHandleMysql_->affect_count());
		break;
	case SQL_TYPE_SELECT:
		affected_rows = 0;
		result = tbl_select(*xmlQuery);
		logger("exec select sql result rows num is: %d", result->length());
		break;
	}

	return result;
}


// ---------------------------------------------------------------

//static bool db_create(const char* dbaddr, const char* dbname,
//	const char* dbuser, const char* dbpass)
//{
//	acl::db_mysql db(dbaddr, "mysql", dbuser, dbpass);
//	if (db.open() == false)
//	{
//		printf("open %s@mysql error, dbuser: %s, dbpass: %s\r\n",
//			dbaddr, dbuser, dbpass);
//		return false;
//	}
//
//	acl::string sql;
//	sql.format("use mysql");
//	if (db.sql_update(sql.c_str()) == false)
//	{
//		printf("'%s' error: %s\r\n", sql.c_str(), db.get_error());
//		return false;
//	}
//	db.free_result();
//
//	sql.format("create database %s character set utf8;\r\n", dbname);
//	if (db.sql_update(sql.c_str()) == false)
//	{
//		printf("'%s' error: %s\r\n", sql.c_str(), db.get_error());
//		return false;
//	}
//	db.free_result();
//
//	sql.format("grant CREATE,DROP,INSERT,DELETE,UPDATE,SELECT on %s.* to %s",
//		dbname, dbuser);
//	if (db.sql_update(sql.c_str()) == false)
//	{
//		printf("'%s' error: %s\r\n", sql.c_str(), db.get_error());
//		return false;
//	}
//	db.free_result();
//
//	sql = "flush privileges";
//	if (db.sql_update(sql.c_str()) == false)
//	{
//		printf("'%s' error: %s\r\n", sql.c_str(), db.get_error());
//		return false;
//	}
//
//	printf("create db(%s) ok\r\n", dbname);
//}
//
//static bool tbl_create(const char* dbaddr, const char* dbname,
//	const char* dbuser, const char* dbpass)
//{
//	if (db.tbl_exists("group_tbl"))
//	{
//		printf("table exist\r\n");
//		return (true);
//	}
//	else if (db.sql_update(CREATE_TBL) == false)
//	{
//		printf("sql error\r\n");
//		return (false);
//	}
//	else
//	{
//		printf("create table ok\r\n");
//		return (true);
//	}
//}

// 添加表数据
const int BaseDao::tbl_insert(acl::query& query) {
//	if (dbHandleMysql_->begin_transaction() == false) {
//		logger_error("begin transaction false: %s", dbHandleMysql_->get_error());
//		return -1;
//	}

	if (dbHandleMysql_->exec_update(query) == false) {
		logger("insert sql fail: %s, error: %s", query.to_string().c_str(), dbHandleMysql_->get_error());
		return -1;
	}

//	if (dbHandleMysql_->commit() == false) {
//		logger_error("commit error: %s", dbHandleMysql_->get_error());
//		return -1;
//	}

	return dbHandleMysql_->affect_count();
}

// 删除表数据
const int BaseDao::tbl_delete(acl::query& query) {
	if (dbHandleMysql_->exec_update(query) == false) {
		logger("delete sql fail: %s, error: %s", query.to_string().c_str(), dbHandleMysql_->get_error());
		return -1;
	}

	return dbHandleMysql_->affect_count();
}

// 更新表数据
const int BaseDao::tbl_update(acl::query& query) {
	if (dbHandleMysql_->exec_update(query) == false) {
		logger("update sql fail: %s, error: %s", query.to_string().c_str(), dbHandleMysql_->get_error());
		return -1;
	}

	return dbHandleMysql_->affect_count();
}

// 查询表数据
const acl::db_rows* BaseDao::tbl_select(acl::query& query) {
	if (dbHandleMysql_->exec_select(query) == false) {
		logger("select sql fail: %s, error: %s", query.to_string().c_str(), dbHandleMysql_->get_error());
		return NULL;
	}

	return dbHandleMysql_->get_result();
}


